

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class AntSimulation {
	
	//parameters
	private int numAnts; //NEW
	//public static final Point startPoint = new Point(300,150);
	
	//Fields
	private int [][] forestground; 
	public defAnt [] antArray;
	private Window window;
	public JPanel simulationArea;
	private boolean started;
	private  int simulationWidth, simulationHeight;
	
	//New
	public int vaporising=5;//specifies how many pheromone trail vapories
	
	//public static boolean wait = false;
	
	public static final Color bgColor = new Color(154,205,50);
	
	private BufferedImage underlayer,previewLayer;
	private boolean wasMinimized=false;
	
	//****NEW
	private Rectangle feed_rectangle,old_feed,old_anthill;
	public  int stat_j;
	public Rectangle anthill_rectangle;
	//private ArrayList<Barricade> barricades;
	
	
	
	public AntSimulation(int width, int height){
		this.simulationWidth=width;
		this.simulationHeight=height;
		this.started=false;
		this.stat_j=0;
		
		
		anthill_rectangle=new Rectangle(new Point(0,0),window.ANTS_INIT/16);
		feed_rectangle=new Rectangle(new Point(0,0),window.FEED_INIT);
		old_anthill= new Rectangle(anthill_rectangle);
		old_feed=new Rectangle(feed_rectangle);

		//barricades=new ArrayList<Barricade>();
		
		
		this.initializeGUI();
		
	}//constructor
	
	/*
	 * getter 
	 */
	public int getSimWidth(){
		return this.simulationWidth;
	}
	
	public int getSimHeight(){
		return this.simulationHeight;
	}
	
	public JPanel getSimArea(){
		return this.simulationArea;
	}
	
	public int getStat_J(){
		return this.stat_j;
	}
	
	
	public void setStat_j(int i){
		stat_j=i;
	}
	
	public int getNumAnts(){
		return this.numAnts;
	}
	
	
	
	public int[][] getForestground(){
		return this.forestground;
	}
	
	public boolean isStarted(){
		return this.started;
	}
	
	public Window getWindow(){
		return this.window;
	}
	
	/*
	 * setter
	 */
	public void setUnderlayerColor(int x, int y, int rgb){
		this.underlayer.setRGB(x, y, rgb);
	}
	
	public void setStarted(boolean started){
		this.started=started;
	}
	
	public void setWasMinimized(boolean min){
		wasMinimized=min;
	}
	//Methods
	public void updateRectangle(int caseNumber){
		switch(caseNumber){
		
		case 1:
				old_anthill=new Rectangle(anthill_rectangle);		
				anthill_rectangle.size=(window.getNumberOfAnts()/16);
				anthill_rectangle.x2=anthill_rectangle.x+anthill_rectangle.size;
				anthill_rectangle.y2=anthill_rectangle.y+anthill_rectangle.size;
				break;
		case 2: 
				old_feed=new Rectangle(feed_rectangle);
				feed_rectangle.size=(window.getSizeFeed());
				break;
		default:;		
	}
		revalidatePreview();
	}//updateRectangle(int caseNumber)
	
	
	public  void draw( Graphics g ){
		for( int i = 0; i < numAnts; i++){
			antArray[i].drawTrail( underlayer.getGraphics() );
		}
		for( int i = 0; i < numAnts; i++ ){
			antArray[i].draw( underlayer.getGraphics() );
		}
		
		g.drawImage(underlayer, 0, 0, null);
		
	}//draw(Graphics g)
	
	public void preview(Graphics g){
		g.drawImage(previewLayer,0,0,null);
	}
	
	private  void initializeGUI(){
		
		this.simulationArea = new JPanel(true) {
			private static final long serialVersionUID = 1L;
			protected void paintComponent( Graphics g ){						
				super.paintComponent( g );
				if(started){
					draw( g );
				}else{
					preview(g);
				}
			}	
		};
		
		this.simulationArea.addMouseListener(new MouseListener(){

			public void mouseClicked(MouseEvent mEV) {
			
				if(window.getFeed()){
					old_feed=new Rectangle(feed_rectangle);
					feed_rectangle.setPosition(mEV.getPoint());
				}else if(window.getAnthill()){
					old_anthill=new Rectangle(anthill_rectangle);
					anthill_rectangle.setPosition(mEV.getPoint());
				}else if(window.getBarricades()){
					//setzen von barricaden
					//merken in arraylist bis sie sich
				}
				revalidatePreview();
			}

			public void mouseEntered(MouseEvent e) {
				// TODO Auto-generated method stub
				
			}

			public void mouseExited(MouseEvent e) {
				// TODO Auto-generated method stub
				
			}

			public void mousePressed(MouseEvent e) {
				// TODO Auto-generated method stub
				
			}

			public void mouseReleased(MouseEvent e) {
				// TODO Auto-generated method stub
				
			}
			
		});
		
		this.window=new Window(this);
		
		//**********NEWfeed
		initializePreviewImage();
		initializeBackgroundImage(simulationWidth,simulationHeight);
		
	}//initializeGUI
	
	
	//******NEW METHOD
	public void newSettings(){
		setStarted(false);
		initializeBackgroundImage(simulationWidth, simulationHeight);
		revalidatePreview();
	}//newSettings()
		
	
	
	private void initializeBackgroundImage( int width, int height ){
		underlayer=(BufferedImage) simulationArea.createImage( width, height );
		Graphics g = underlayer.getGraphics();
		g.setColor( bgColor );
		g.fillRect(0, 0, width, height);
	}
	
	
	private void initializePreviewImage(){
		previewLayer=(BufferedImage)simulationArea.createImage(simulationWidth,simulationHeight);
		Graphics g = previewLayer.getGraphics();
		g.setColor(bgColor);
		g.fillRect(0,0,simulationWidth,simulationHeight);
	}
	
	private void revalidatePreview(){
		
		/*feed_rectangle.size=(window.getSizeFeed());
		anthill_rectangle.size=(window.getNumberOfAnts()/16);
*/
		Graphics g = previewLayer.getGraphics();
		
		//delete from view old version
		g.setColor(bgColor);
		old_feed.drawPreviewPosition(g);
		old_anthill.drawPreviewPosition(g);
		
		g.setColor(Color.cyan);
		feed_rectangle.drawPreviewPosition(g);
		g.setColor(Color.magenta);
		anthill_rectangle.drawPreviewPosition(g);

		simulationArea.repaint();
	}//drawFeedDepot(boolean preview)
	
	public void initialzeSimulation(){
		
		forestground = new int [simulationWidth][simulationHeight];
		
		Ant.DIRECTION [] tmp = Ant.defaultPrefDir;
		
	
		System.out.println("Simulationsbedingungen initialisiert");
		
		//*******NEW
		
		//belegt forestground mit defaultwerten
		
		for( int i = 0; i < simulationWidth; i++ ){
			for( int j = 0; j < simulationHeight; j++ ){
					forestground[i][j] = 1;//tmpColor;
			}//for - j
		}//for - i
		
		//Hilfsvariablen 
		int feed_size=feed_rectangle.size;
		int f_x=feed_rectangle.x;
		int f_y=feed_rectangle.y;
		
		for(int i=f_x;i<f_x+feed_size;i++){
			for(int j=f_y;j<f_y+feed_size;j++){
				forestground[i][j] = -270;
				underlayer.setRGB( i, j, Color.cyan.getRGB() );
			}
		}

		
		numAnts=window.getNumberOfAnts();
		antArray = new Ant[numAnts];
			
		Random rand = new Random();
		Point start = anthill_rectangle.getPosition();
		//damit ameisen dort noch nicht  starten
		//config size s.o.
		
		start.x--;
		start.y--;
		int anthill_size=anthill_rectangle.size;
		int config_size=anthill_size+2;
		//test
		int a_x=anthill_rectangle.x;
		int a_y=anthill_rectangle.y;
		
		//test
		System.out.println(anthill_rectangle.x2);
		System.out.println("Futterhuegel:"+feed_rectangle.x+"     "+feed_rectangle.y);
		System.out.println("Ameisenhuegel: Mitte ("+anthill_rectangle.getMidPointX()+","+anthill_rectangle.getMidPointY()+")");
		System.out.println("huegel links oben: ("+anthill_rectangle.x+","+anthill_rectangle.y+")");
		System.out.println("huegel rechts unten: ("+anthill_rectangle.x2+","+anthill_rectangle.y2+")");
		for(int i=a_x;i<a_x+anthill_size;i++){
			for(int j=a_y;j<a_y+anthill_size;j++){
				forestground[i][j] = -255;
				underlayer.setRGB( i, j, Color.green.getRGB() );
			}
		}
		//die Startpositionen der Ameisen bestimmen
		for( int i = 0; i < numAnts; i++ ){
			Point newP=start;
			switch (i%4){	
			case 0: newP=new Point(start.x+rand.nextInt(config_size),start.y);break;
					//new Ant( new Point( start.x+ rand.nextInt(anthill_size), start.y + rand.nextInt(anthill_size) )
					//		, tmp[ i/(numAnts/16) ],this );
			case 1:	newP=new Point(start.x+(config_size),start.y+rand.nextInt(config_size));break;
			case 2:newP=new Point(start.x,start.y+rand.nextInt(config_size));break;
			case 3:newP=new Point(start.x+rand.nextInt(config_size),start.y+config_size);break;					
			}
			antArray[i]=new Ant(newP,tmp[i/(numAnts/8)],this);
		}
		
//for - i
		
	}//initializeSimulation()

	
	public  boolean isCorrectlySet(){
		
		if(anthill_rectangle.interlapse(feed_rectangle)
				||feed_rectangle.interlapse(anthill_rectangle)
				||anthill_rectangle.isOutOfBounds(simulationWidth, simulationHeight)
				||feed_rectangle.isOutOfBounds(simulationWidth, simulationHeight)){

			return false;
		}
			return true;
	}//isCorrectlySet
	
	private  void repaintSimArea() {
		SwingUtilities.invokeLater(new Runnable() {
			 public void run() {
				 simulationArea.repaint();
			 }//run
		 });
		 //SwingUtilities.invokeLater(rp);
	}//repaintSimArea(final JPanel panel)

	//neu
	 private  void revalidateForestGround(){
		    /*
			Graphics g = underlayer.getGraphics();
			g.setColor( bgColor );
			g.fillRect(0, 0, simulationWidth, simulationHeight);
			int diff = 1;
			boolean lessNull, isFood;
			for( int i = 0; i < forestground.length; i++ ){
				for( int j = 0; j < forestground[0].length; j++ ){
					lessNull = false;
					isFood = false;
					int tmpGround = forestground[i][j];
					if( tmpGround < 0 ){
						lessNull = true;
						tmpGround *= -1;
					}
					if( tmpGround > 255 )
						isFood = true;
					tmpGround -= diff;
					if( tmpGround <= 0 )
						tmpGround = 1;
					if( isFood && tmpGround <= 255 ){
						underlayer.setRGB( i, j, Color.cyan.getRGB() );
						tmpGround = 256;
					}
					if( lessNull )
						tmpGround *= -1;
					forestground[i][j] = tmpGround;
				}
			}*/
		 
		 Graphics g = underlayer.getGraphics();
		 
		 for( int i = 0; i < forestground.length; i++ ){
				for( int j = 0; j < forestground[0].length; j++ ){
					//System.out.println("Waldboden vorher"+forestground[i][j]);
					if(forestground[i][j]>0){//evtl duftspur
						if (forestground[i][j]<=255){//kein futter soll beruecksichtigt werden
						
							forestground[i][j]-=vaporising;
							if(forestground[i][j]<=0){//damit es immer positiv bleibt
								forestground[i][j]=1;
								
							
							
						}
							//hier wird neu gemalt
							int tmp=forestground[i][j];
							Color tmpColor = new Color( -tmp/2+154, 205-tmp/2, 50+tmp/2 );
							g.setColor(tmpColor);
							g.fillRect(i, j, 1	, 1);
						}
					}
					else{//negativ ->ameise
						if(forestground[i][j]>=-255){
						
							forestground[i][j]+=vaporising;
							if(forestground[i][j]>=0){//damit es immer negativ bleibt
								forestground[i][j]=-1;	
								
							}
							//hier brauch nicht neu gemalt werden weil ne ameise draufsteht
						
						}
					}
					
					//System.out.println("Waldboden nachher"+forestground[i][j]);
				}
			}
		 
		 //ueberschuss gibts nicht mehr
		 	for(int i=0;i<numAnts;i++){
		 		antArray[i].getPtrail().getUeberschuss().clear();
		 		antArray[i].getPtrail().getAbnahme().clear();
		 	}
		}
	 
	 
	
	public  void simulate(int j) throws InterruptedException{
		for(int i = 0; i < 100000; i++ ){
			
			/*
			 * Quellcode falls er mittig unterbricht - das tut er aber meistens nicht...(vllt wegen sleep)
			 * sonst wuerde auch einfaches j=0 reichen bin mir aber nicht 100%ig sicher ;)
			 * koennte wohl in einem von viiiielen faellen schief gehen
			 */
			for( stat_j = j; stat_j < numAnts; stat_j++ ){
//				System.out.println("\n"+j+". Ameise\n");
				antArray[stat_j].stepForward();
				
			}//for - j
			j=0;
			
			if(i%100==0){
				revalidateForestGround();
				//System.out.println("jojo");
		}
			
			repaintSimArea();
			
		
//			if (i==2) System.exit(0);
//			if (i==200) break;

				Thread.sleep(35);
		
		}//for - i
		System.out.println("Default end of simulation");

	}//simulate()

}//class
